iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
1

寫在前面

R 語言是一個用於統計與分析的語言
概念上類似於工程學上常見的另外一門語言 Matlab
這種用於數學計算的語言跟我們以往學過的語言不管是語法還是使用概念都大不相同

先來說說我跟 Matlab 的抱怨淵源吧,Matlab 是當年機械系入學時的必修課
當時老師上課只說了一句

下一堂課開始每堂課都有作業,所以你們要自己去找軟體

然後全宿舍的同學都像瘋了一樣到處去找學生版,有些同學也依靠著可靠的直屬拿到了學長版
當然最終還是有些同學沒生出來或沒要到(當時根本沒人買得起隨身硬碟,都要靠 1G 或 4G 的隨身碟傳好幾次,不然就是要放著連結讓他慢慢抓,然後當時學校網路又有限流量)
不然就是拿到了安裝檔卻沒辦法安裝,或是安裝了卻跑不動

總之當年我們這群學生都還沒開始寫程式便對程式留下了一堆不好的印象

課程開始後又從基本資料型態 bits 開始教,實際寫程式又寫矩陣相關
當年這群從高職上去的學生根本聽都沒聽過

更糟糕的是別堂上力學的老師懶得推導方程式就叫我們自己用 Matlab 算結果

你們有學 Matlab 吧? 這個隨便寫幾行就可以證明了,很簡單的

然後大家就爆炸了

扯遠了,讓我們回來看 R 吧

R 語言與 Matlab 相反,是一個完全免費的語言(自由軟體)
所以就沒有正版,快樂版,學生版之分了(所以我們到底為什麼要用 Matlab?)

而且由於是開源的語言,因此想得到的功能都有人寫過 package
反正工程學上需要的是解決問題而不是研究問題,比起怎麼用更重要的是用什麼
讓工程師們可以更專注於問題上而不是型別及記憶體釋放之類底層的事物
(當然,如果你要也是可以,畢竟 R 是開源的,所以我們到底為什麼要學 Matlab?)

開源的另外一個好處是如果今天有一個新的演算法被提出來,基本上不用等太久就可以看到有人寫完丟出來可以用了,而 Matlab 你必須要看官方的心情(所以我們到底為什麼要學 Matlab?)

同時兩者已經經歷死亡交叉了
https://ithelp.ithome.com.tw/upload/images/20200920/20127836KUEkg0c9U1.png
在這個疫情的時代,分析用工具的排名居然還能往下掉(所以我們到底為什麼要學 Matlab?)

而且如果你想用 R 做一些網路功能的運用也可以,爬蟲當然也能寫
甚至還能連接大部分的資料庫(歸功於開源)
你開心的話想去接 TensorFlow 之類的深度學習模型也辦得到
(所以我們到底為什麼要學 Matlab?)

重點是相當輕量,你不必擔心電腦老舊跑不動(所以我們到底為什麼要學 Matlab?)

當然,如果你只想學或使用成熟的東西(而且又有錢)的話,當然還是可以選擇使用 Matlab
就像是作業系統可以選擇 Windows/MacOS 或是 linux 一樣

先去安裝 R 吧
如果對數學計算用的語言沒興趣的人可以跳過這堂課,因為基本上 R 跟其他語言沒有太大關係
如果想學習這門語言的人我不建議你使用 docker,因為 RStudio 才會有良好的使用者體驗

所以記得安裝 R 時要順便安裝 RStudio

RStudio

點開 RStudio 你應該會看到如下圖的畫面
如果你的畫面底色不是黑色也沒關係,這個是我刻意調的,不是代表你們的 RStudio 故障了

https://ithelp.ithome.com.tw/upload/images/20200920/20127836K7ZAvMQ9Jx.png

每個區域上面都還有頁籤可以切換

現在你可以去主畫面的 Console 頁籤做一些運算了
跟我們以往使用瀏覽器的 console 或是 irb 之類的互動環境一樣

玩夠了之後可以去你的工作目錄下面建立一個副檔名是.R 的檔案,然後在 RStudio 的右下角環境區打開他

如圖

https://ithelp.ithome.com.tw/upload/images/20200920/20127836GR5yoexR1A.png

左下角是我剛才試玩的程式碼,如果你有宣到變數將會出現在右上角

左上角的主畫面的程式碼我馬上就會給你了,如下

程式碼

input <- "2801"
choose <- 1 #(1)T to H (2)H to T

returnAE <- function(input){
    if (input<10){
        output <- input
    }else {
        switch (input-9,
            output <- "A",
            output <- "B",
            output <- "C",
            output <- "D",
            output <- "E",
            output <- "F"
        )
    }
    output
}

t2h <- function(input){
    for (i in 0:16){
        for (j in 0:16){
            for (k in 0:16){
                if (16^2*i+16^1*j+16^0*k == input){
                    str <- sprintf("%s%s%s",returnAE(i), returnAE(j), returnAE(k))
                }
            }
        }
    }
    str
}

h2t <- function(input){
   output = 0
   n <- nchar(input)
   i <- 1
   while (i<n+1){
       output = output + (AEreturn(substr(input,i,i)))*16^(n-i)
       i= i+1
   }
   output
}

AEreturn <- function(input){
    switch (input,
        "A" = output <- 10,
        "B" = output <- 11,
        "C" = output <- 12,
        "D" = output <- 13,
        "E" = output <- 14,
        "F" = output <- 15,
        output <- as.integer(input)
    )
    output
}


switch (choose , output <- t2h(input), output <- h2t(input))
output

把他們貼上你開啟的檔案吧
貼上後記得存檔

https://ithelp.ithome.com.tw/upload/images/20200920/20127836JTrkbwRCLP.png

就這樣?

沒錯,就這樣

結構

R 算是直譯式的語言,所以沒有明顯的程式進入點
行尾不需要;
如果需要註解可以用#

輸入及輸出

這邊我們沒有使用傳統的對終端機輸入的互動式程式
如果你想要用可以使用

choose <- readline()

print(choose)

的方式來表現輸入及輸出(修改後記得存檔再執行)

這邊我們使用的是

input <- "3554"
choose <- 1

將變數丟入的方式,所以如果你想要變更進位轉換或是輸入的數字直接修改這裡的值即可

由於 R 採用動態型別系統,因此你在宣告變數時可以不給他變數的型別

方法定義

returnAE <- function(input){
    if (input<10){
        output <- input
    }else {
        switch (input-9,
            output <- "A",
            output <- "B",
            output <- "C",
            output <- "D",
            output <- "E",
            output <- "F"
        )
    }
    output
}

是不是感覺有點像反過來的 js 箭頭函式?

關鍵字使用 function,方法的名稱則放在最前面,中間用<-區隔
動態型別的關係,不需要宣告參數及輸出的型別

要回傳的值跟 Raku 一樣放在最後一行,會自己回傳回去

邏輯

R 的 if 跟常見的 if 相同,使用()跟{}

switch 就比較特別了,注意到這裡

switch (input-9,
    output <- "A",
    output <- "B",
    output <- "C",
    output <- "D",
    output <- "E",
    output <- "F"
)

switch 的條件並不單獨放在()內,而是連同子句一起

一開始的 input-9 是為了對後面做準備
如同一開始說的,R 是為了數學而設計,因此他有一個特別的 switch 用法
在 switch 的第一的參數有了數值後,會根據數值去找後面的位置
比方說當 input 為 12 時,由於 input-9 為 3,output 的值就會是"C"

當然,如果你需要一般的 switch 也是有,用法也類似,詳細就請各位自己去查看看吧

迴圈

往下看到t2h裡面的迴圈吧

for (i in 0:16){
    for (j in 0:16){
        for (k in 0:16){

由於在科學的運算裡很常用到迴圈,因此寫法也比其他語言簡單
0:16表示不包含16,也就是執行15次

冪次

同樣的,在科學運算擅長的R寫出冪次運算也相當直覺

if (16^2*i+16^1*j+16^0*k == input)

可以直接用^,夠直覺了吧

字串處理

R也有跟其他語言相同的字串整理,如下

str <- sprintf("%s%s%s",returnAE(i), returnAE(j), returnAE(k))

跟golang一樣填充字元使用%s
方法不印出東西而是將值丟入到變數

字元處理

往下看到將十六進位轉成十進位的h2t吧

h2t <- function(input){
   output = 0
   n <- nchar(input)
   i <- 1
   while (i<n+1){
       output = output + (AEreturn(substr(input,i,i)))*16^(n-i)
       i= i+1
   }
   output
}

nchar是確認字串長度的方法
同時注意到下面的i以往的語言我們都是宣告為0,這裡宣告為1
理由在於R的陣列index是由1開始,而非從0開始(這樣你可以知道為什麼剛才switch是從1而非從0開始了吧)
所以在while裡面才是i<n+1而非n
之後的substr(input,i,i)是將字串的值取出,從第i個到第i個
也就是說如果今天i為3,那他就是取出字串的第三個字元
之後使用AEreturn將十六進位轉成十進位,之後才與16的冪次相乘

switch

switch有另外一種寫法,往下看到AEreturn吧

AEreturn <- function(input){
    switch (input,
        "A" = output <- 10,
        "B" = output <- 11,
        "C" = output <- 12,
        "D" = output <- 13,
        "E" = output <- 14,
        "F" = output <- 15,
        output <- as.integer(input)
    )
    output
}

他會去跟每個條件做比對,之後執行=後面的程式
如果比對沒有結果轉型並回傳
(注意這裡會有bug,如果輸入GH之類的就會原地解散)

以上就是R的基本語法

不過R這門語言並不是用來專門做這種程式的,更適合用於科學與統計
這次寫的內容只是為了要展示R的基本操作跟語法
實際上用於研究會需要其他操作

比方說單行執行

不過在那之前先讓我們清空歷史紀錄(就像瀏覽紀錄那樣)

https://ithelp.ithome.com.tw/upload/images/20200920/20127836t759xxhkmD.png

點擊紅色框框內的掃把可以清空已經紀錄的變數跟已經執行過的歷史紀錄

然後把你的游標指向任何一行程式碼後點擊綠色框框內的按鈕(隨便一個都可以)
這時你可以觀察下方的執行紀錄跟游標的位置
是不是發現程式會按照你的游標決定執行到哪裡,這樣在除錯與找變數變動的過程就會比較容易

詳細用法就交給各位去體會拉

我們來複習語法吧

  • 基本結構
    • 使用RStudio可以更清楚知道程式的運作與變數的內容
    • 直譯式語言,從程式碼第一行開始執行
    • 行尾不需要;
  • 印出/讀取
    • print可以印出
    • readline可以讀取輸入
  • 方法的結構
    • 使用<- ,關鍵字是function
    • 動態型別,不必提前命名回傳值的型別
    • 使用{}來宣告方法的範圍
    • 預設回傳方法的最後一行
  • 邏輯控制
    • switch的用法有兩種,兩種的結構都跟以往不同,需要注意
    • if的用法跟往常一樣
  • 迴圈控制
    • for跟while跟其他語言一樣
  • 型別
    • 動態+弱型別系統
  • 冪次計算
    • 使用^而不使用一般的pow

這樣最常用的幾個語言基本上我們都學完了
明天我們先不學語言,而是來學工具
git


上一篇
Rust 安全第一
下一篇
git 新版本有問題? 那就回到上個版本
系列文
你會十五種程式語言?不,我會十五種HelloWorld.為了避免這種狀況,因此寫了這篇:淺入淺出十五種程式語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
skycover
iT邦新手 4 級 ‧ 2020-09-20 18:29:41

如果有任何寫不清楚或是觀念沒有很明白的話請留言告知我
會盡快補上

如果有任何寫錯的地方也麻煩留言告知我
會盡快修正

感謝各位

我要留言

立即登入留言